home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / util / cli / SmartPrompt.lha / SmartPrompt / SmartPrompt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-09-26  |  9.0 KB  |  534 lines

  1. /* $VER: SmartPrompt v1.0 (26.09.98) by Adrian Zurek
  2. ** :ts=4
  3. **
  4. ** This program is free software; you can redistribute it and/or modify
  5. ** it under the terms of the GNU General Public License as published by
  6. ** the Free Software Foundation; either version 2 of the License, or
  7. ** (at your option) any later version.
  8. **
  9. ** This program is distributed in the hope that it will be useful,
  10. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. ** GNU General Public License for more details.
  13. **
  14. ** You should have received a copy of the GNU General Public License
  15. ** along with this program; see the file COPYING. If not, write to
  16. ** the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. #define __USE_SYSBASE
  20.  
  21. #include <exec/types.h>
  22.  
  23. #include <proto/exec.h>
  24. #include <proto/dos.h>
  25. #include <proto/multiuser.h>
  26. #include <proto/usergroup.h>
  27.  
  28. #include <exec/execbase.h>
  29. #include <exec/memory.h>
  30.  
  31. #include <string.h>
  32. #include <stdlib.h>
  33.  
  34.  
  35.  
  36. /************************************************************************/
  37. /***************** these constants describe our program *****************/
  38. /************************************************************************/
  39. #define PROGRAM_NAME    "SmartPrompt"
  40. #define PROGRAM_VERSION    " v1.0 "
  41.  
  42. #ifdef    __AMIGADATE__
  43. #    define PROGRAM_DATE    __AMIGADATE__
  44. #elif defined (__DATE__)
  45. #    define PROGRAM_DATE    "(" __DATE__ ")"
  46. #else
  47. #    define PROGRAM_DATE    "(26.09.98)"
  48. #endif
  49. /************************************************************************/
  50.  
  51. /* NewPrompt's version string */
  52. const char *Version="\0$VER: " PROGRAM_NAME PROGRAM_VERSION PROGRAM_DATE;
  53.  
  54.  
  55. #define KICKVERSION        37
  56.  
  57. #define FMTSTR_MAX        160
  58. #define OUTSTR_MAX        255
  59.  
  60. enum {OK,NO_KICK,NO_VAR};
  61.  
  62.  
  63. /*** global variables ***/
  64.  
  65. extern struct ExecBase *SysBase;
  66. struct muBase *muBase=NULL;
  67. struct Library *UserGroupBase=NULL;
  68.  
  69. char FormatStr[FMTSTR_MAX+1];
  70. char OutStr[OUTSTR_MAX+1]="\0";
  71. char *FormatPtr=FormatStr;
  72.  
  73.  
  74. /*** function prototypes (13 functions) ***/
  75. void    cleanup( UBYTE );
  76.  
  77. void    stradd( char * );
  78. void    getdevicename( char *, char * );
  79. UBYTE    countdirs( char * );
  80. UBYTE    getlimit( void );
  81. void    getdir( void );
  82. void    gettime( UBYTE );
  83. void    gethostname( void );
  84. void    getuser( void );
  85. BOOL    checkroot( void );
  86. void    openlibs( void );
  87. void    process( UBYTE );
  88.  
  89. void    __main( char * );
  90.  
  91.  
  92.  
  93. /* function frees all(??) resources allocated by program,    */
  94. /* prints out operation status and exits.                     */
  95. void cleanup(UBYTE exception)
  96. {
  97. if (exception)
  98.     if (exception==NO_KICK)
  99.         Write(Output(),"This program needs Kickstart 2.04 (V37) to run!\n",49);
  100.     else
  101.         Printf("%s: No $SPROMPT variable found!\n",PROGRAM_NAME);
  102.  
  103. /* close libraries */
  104. CloseLibrary((struct Library *)muBase);
  105. CloseLibrary(UserGroupBase);
  106.  
  107. exit (exception);
  108. }
  109.  
  110.  
  111.  
  112. void stradd(char *string)
  113. {
  114. UBYTE remaining=OUTSTR_MAX-strlen (OutStr);
  115.  
  116. if (remaining<strlen (string))
  117.     string[remaining]='\0';
  118.  
  119. strcat (OutStr,string);
  120. }
  121.  
  122. void getdevicename(char *volume,char *device)
  123. {
  124. struct DosList *dl;
  125. struct FileLock *l;
  126. BPTR lock;
  127.  
  128. if (lock=Lock(volume,ACCESS_READ))
  129. {
  130.     l=BADDR(lock);
  131.  
  132.     dl=LockDosList(LDF_DEVICES | LDF_READ);
  133.  
  134.     while (dl=NextDosEntry(dl,LDF_READ | LDF_DEVICES))
  135.         if (dl->dol_Task==l->fl_Task)
  136.         {
  137.             strcat (device,(UBYTE *)BADDR(dl->dol_Name)+1);
  138.             break;
  139.         }
  140.  
  141.     UnLockDosList(LDF_DEVICES | LDF_READ);
  142.     UnLock(lock);
  143. }
  144.  
  145. if (!*device)
  146.     strcat (device,volume);
  147. }
  148.  
  149. /* function returns number of components of given pathname */
  150. UBYTE countdirs(char *pathname)
  151. {
  152. char *ptr=pathname;
  153. UBYTE cnt=1;
  154.  
  155. if (pathname[strlen (pathname)-1]!=':')
  156. {
  157.     do
  158.         cnt++;
  159.     while (ptr=strchr (++ptr,'/'));
  160. }
  161.  
  162. return (cnt);
  163. }
  164.  
  165. UBYTE getlimit(void)
  166. {
  167. char lim[3];
  168. UBYTE x=0;
  169.  
  170. if (strlen (FormatPtr)>2)
  171. {
  172.     strncpy (lim,++FormatPtr,2); lim[2]='\0';
  173.     FormatPtr++;
  174.     x=(UBYTE)atoi (lim);
  175. }
  176.  
  177. return (x);
  178. }
  179.  
  180. void getdir(void)
  181. {
  182. char dirname[100],volume[30]="\0";
  183. char *colon,*ptr;
  184. BOOL lastpath=TRUE,ixstyle=FALSE,device=FALSE;
  185. UBYTE limit=0,count;
  186.  
  187. FormatPtr++;
  188. while (*FormatPtr!='}')
  189. {
  190.     if (*FormatPtr=='\0')
  191.         return;
  192.  
  193.     switch (*FormatPtr)
  194.     {
  195.     case 'd':
  196.         device=TRUE;
  197.         break;
  198.     case 'a':
  199.         ixstyle=FALSE;
  200.         break;
  201.     case 'x':
  202.         ixstyle=TRUE;
  203.         break;
  204.     case 'p':
  205.         lastpath=TRUE;
  206.         limit=getlimit();
  207.         break;
  208.     case 'P':
  209.         lastpath=FALSE;
  210.         limit=getlimit();
  211.         break;
  212.     }
  213.  
  214.     FormatPtr++;
  215. }
  216.  
  217. GetCurrentDirName(dirname,99);
  218.  
  219. colon=strchr (dirname,':');
  220.  
  221. if (ixstyle)
  222.     strcpy (volume,"/");        /* add "/" at the beginning */
  223.  
  224. if (device || ((ptr=strchr (dirname,' ')) && (ptr<colon)))
  225.     getdevicename(dirname,volume);
  226. else
  227.     strncat (volume,dirname,colon-dirname);
  228.  
  229. if (!ixstyle)
  230.     strcat (volume,":");
  231.  
  232. /* colon ptr now points on the char next to the ':' */
  233. colon++;
  234.  
  235. if ((count=countdirs(dirname))==1)
  236.     stradd(volume);
  237. else if (lastpath)
  238. {
  239.     if ((!limit) || (limit>=count))
  240.     {
  241.         stradd(volume);
  242.         if (ixstyle)
  243.             stradd("/");
  244.         stradd(colon);
  245.     }
  246.     else
  247.     {
  248.         ptr=colon-1;
  249.  
  250.         while (--count>limit)
  251.             if (!(ptr=strchr (++ptr,'/')))
  252.                 break;
  253.  
  254.         stradd(++ptr);
  255.     }
  256. }
  257. else
  258. {
  259.     UBYTE len=strlen (colon)+strlen (volume);
  260.  
  261.     if (ixstyle)
  262.         len++;
  263.  
  264.     if (!limit)
  265.         limit=255;
  266.  
  267.     stradd(volume);
  268.  
  269.     if (len>limit)
  270.     {
  271.         while (count-->(ixstyle ? 1 : 2))
  272.             stradd("/");
  273.  
  274.         ptr=colon;
  275.         while (*ptr++);            /* move to the end of string */
  276.         while (*--ptr!='/');    /* and then look for '/' char starting from the end */
  277.         stradd(++ptr);
  278.     }
  279.     else
  280.     {
  281.         if (ixstyle)
  282.             stradd("/");
  283.  
  284.         stradd(colon);
  285.     }
  286. }
  287. }
  288.  
  289. enum {TIME,DATE,WEEKDAY};
  290.  
  291. void gettime(UBYTE type)
  292. {
  293. struct DateTime dtime;
  294. char timestr[LEN_DATSTRING+1];
  295.  
  296. DateStamp(&dtime.dat_Stamp);
  297.  
  298. dtime.dat_Format=FORMAT_DOS;
  299. dtime.dat_Flags=0;
  300. dtime.dat_StrDay=(type==WEEKDAY) ? timestr : NULL;
  301. dtime.dat_StrDate=(type==DATE) ? timestr : NULL;
  302. dtime.dat_StrTime=(type==TIME) ? timestr : NULL;
  303.  
  304. DateToStr(&dtime);
  305.  
  306. stradd(timestr);
  307. }
  308.  
  309. void gethostname(void)
  310. {
  311. char host[13];
  312. char *ptr;
  313.  
  314. if (GetVar("hostname",host,13,GVF_GLOBAL_ONLY)!=-1)
  315. {
  316.     if (ptr=strchr (host,'.'))
  317.         *ptr='\0';
  318.  
  319.     stradd(host);
  320. }
  321. else
  322.     stradd("AmigaOS");
  323. }
  324.  
  325. void getuser(void)
  326. {
  327. char userid[muUSERIDSIZE];
  328.  
  329. strcpy (userid,"nobody");
  330.  
  331. if (muBase)
  332. {
  333.     struct muUserInfo *info;
  334.     UWORD uid=muGetTaskOwner(NULL)>>16;
  335.  
  336.     if (info=muAllocUserInfo())
  337.     {
  338.         info->uid=uid;
  339.         if (muGetUserInfo(info,muKeyType_uid))
  340.             strcpy (userid,info->UserID);
  341.  
  342.         muFreeUserInfo(info);
  343.     }
  344. }
  345. else if (UserGroupBase)
  346. {
  347.     uid_t uid=getuid();
  348.     struct passwd *pw;
  349.  
  350.     if (pw=getpwuid(uid))
  351.         strcpy (userid,pw->pw_name);
  352. }
  353.  
  354. stradd(userid);
  355. }
  356.  
  357. BOOL checkroot(void)
  358. {
  359. if (muBase)
  360. {
  361.     if (muROOT_UID==(muGetTaskOwner(NULL)>>16))
  362.         return (TRUE);
  363. }
  364. else if (UserGroupBase)
  365. {
  366.     if (!getuid())
  367.         return (TRUE);
  368. }
  369.  
  370. return (FALSE);
  371. }
  372.  
  373. void openlibs(void)
  374. {
  375. struct Library *lib;
  376. BOOL found_mufs=FALSE,found_ug=FALSE;
  377.  
  378. Forbid();
  379.  
  380. lib=(struct Library *)SysBase->LibList.lh_Head;
  381.  
  382. do
  383. {
  384.     if (!found_mufs)
  385.         if (!strcmp (lib->lib_Node.ln_Name,MULTIUSERNAME))
  386.         {
  387.             found_mufs=TRUE;
  388.             break;
  389.         }
  390.  
  391.     if (!found_ug)
  392.         if (!strcmp (lib->lib_Node.ln_Name,"usergroup.library"))
  393.             found_ug=TRUE;
  394.  
  395.     lib=((lib==(struct Library *)SysBase->LibList.lh_TailPred) ? NULL :
  396.         (struct Library *)lib->lib_Node.ln_Succ);
  397. }
  398. while (lib);
  399.  
  400. Permit();
  401.  
  402. if (found_mufs)
  403.     muBase=(struct muBase *)OpenLibrary(MULTIUSERNAME,MULTIUSERVERSION);
  404. else if (found_ug)
  405.     UserGroupBase=OpenLibrary("usergroup.library",1);
  406. }
  407.  
  408. enum {GLOBAL_,ROOT_DO,ROOT_IGNORE};
  409.  
  410. void process(UBYTE type)
  411. {
  412. while (*++FormatPtr!='\0')
  413. {
  414.     if (*FormatPtr=='%')
  415.     {
  416.         if (type!=ROOT_IGNORE)
  417.         {
  418.             if (*++FormatPtr=='\0')
  419.                 break;
  420.  
  421.             switch (*FormatPtr)
  422.             {
  423.             case 'p':
  424.                 getdir();
  425.                 break;
  426.             case '%':
  427.                 stradd("%");
  428.                 break;
  429.             case 'u':
  430.                 getuser();
  431.                 break;
  432.             case 'h':
  433.                 gethostname();
  434.                 break;
  435.             case 'q':
  436.                 stradd("\"");
  437.                 break;
  438.             case 'b':
  439.                 stradd("{");
  440.                 break;
  441.             case 'B':
  442.                 stradd("}");
  443.                 break;
  444.             case 'R':
  445.                 if (type==GLOBAL_)
  446.                     process(checkroot() ? ROOT_DO : ROOT_IGNORE);
  447.                 break;
  448.             case 'r':
  449.                 if (type==GLOBAL_)
  450.                     process(checkroot() ? ROOT_IGNORE : ROOT_DO);
  451.                 break;
  452.             case 't':
  453.                 gettime(TIME);
  454.                 break;
  455.             case 'd':
  456.                 gettime(DATE);
  457.                 break;
  458.             case 'w':
  459.                 gettime(WEEKDAY);
  460.                 break;
  461.             }
  462.         }
  463.     }
  464.     else
  465.     {
  466.         char ch[2]=" ";
  467.         BOOL write2=TRUE;
  468.  
  469.         if (type!=GLOBAL_)
  470.             if (*FormatPtr=='{')
  471.                 write2=FALSE;
  472.             else if (*FormatPtr=='}')
  473.                 return;
  474.             else if (type==ROOT_IGNORE)
  475.                 write2=FALSE;
  476.  
  477.         if (write2)
  478.         {
  479.             *ch=*FormatPtr;
  480.             stradd(ch);
  481.         }
  482.     }
  483. }
  484. }
  485.  
  486.  
  487. void __stdargs __main(char *line)
  488. {
  489. extern struct WBStartup *_WBenchMsg;
  490.  
  491. /* get Kickstart version */
  492. if (SysBase->LibNode.lib_Version<KICKVERSION)
  493.     cleanup(NO_KICK);
  494.  
  495. if (_WBenchMsg)
  496. {
  497.     ReplyMsg((struct Message *)_WBenchMsg);
  498.     cleanup(OK);
  499. }
  500.  
  501. if (GetVar("SPROMPT",FormatStr,FMTSTR_MAX,NULL)==-1)
  502.     cleanup(NO_VAR);
  503.  
  504. openlibs();
  505.  
  506. FormatPtr=FormatStr-1;
  507.  
  508. process(GLOBAL_);
  509.  
  510. PutStr(OutStr);
  511.  
  512. cleanup(OK);
  513. }
  514.  
  515. /*
  516. %u - userid
  517. %h - hostname
  518. %R{} - root string
  519. %r{} - non-root string
  520. %% - '%' char
  521. %q - '"' char
  522. %b - '{' char
  523. %B - '}' char
  524. %p{} - path:
  525.     a - Amiga style pathes (default)
  526.     x - UNIX style pathes
  527.     d - device names instead of volume names
  528.     pxx - partial path style no. 1: "path" shows only "xx" lasts components of path (0 prints all and is the default)
  529.     Pxx - partial path style no. 2: "work:////path" and is limited to "xx" number of chars
  530. %t - time in format hh:mm
  531. %d - date
  532. %w - weekday
  533. */
  534.